


import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;

import realtime.SendDocumentState;


import messagepasser.DocInfo;
import messagepasser.DocListDAOSQL;
import messagepasser.DocPermissions;
import messagepasser.DocReadDAOSQL;
import messagepasser.LoginDAOSQL;
import messagepasser.PermissionsDAOSQL;
import messagepasser.UserInfo;
import messagepasser.UserInfoDAOSQL;

public class Server_Servant extends UnicastRemoteObject implements Server {
	
	Map <Integer, Client> onlineUsers = new HashMap <Integer, Client>();
	HeartBeat hb;
	Server s;
		
	public Server_Servant(String serverType, String ip) throws RemoteException {
		
	    // start the heartbeat
		Timer t = new Timer();
		hb = new HeartBeat(onlineUsers, t, serverType, ip);
		t.schedule(hb, 10000, 5000);
		
	}	
	public UserInfo login (String user, String pwd, String ipAddr, int port) throws RemoteException {
		UserInfo userInformation = null;
		LoginDAOSQL logindao = new LoginDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","userprofile");
		String pwddb = logindao.getPwd(user);
		if(pwddb!=null){
			if (pwddb.equals(pwd)){ 
				System.out.println("Login Successful");
				int userid = logindao.getUserID(user);
				userInformation = new UserInfo(userid, user, true, ipAddr, port);
				logindao.setIpPort(ipAddr, port, userid);
			}
			else {
				System.out.println("Login Successful");
			}
		}
		else {
			System.out.println("Login Unsuccessful");
			return null;
		}
		
		Set <Integer> userIDs = onlineUsers.keySet();
		for (Integer i : userIDs) {
			try {
				onlineUsers.get(i).newUserOnline(userInformation);
			}
			catch (Exception e) {
				//onlineUsers.remove(i);
				System.out.println ("user may be offline");
			}
		}
		
		return userInformation; 			

	}
	
	public List<DocInfo> getDocuments(int userId) throws RemoteException {
	
		DocListDAOSQL docDAO = new DocListDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","document");
		return docDAO.getDocsInfo(userId);
		 			
	}
	
	public List<UserInfo> getonlineUsers(int userId) throws RemoteException {
	// TODO Auto-generated method stub
		UserInfoDAOSQL userDAO = new UserInfoDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","user");
		return (new ArrayList<UserInfo>(Arrays.asList(userDAO.getuserinfo(userId))));
	}
	
	@Override
	public void register(Client c, int userId) throws RemoteException {
		this.onlineUsers.put(userId, c);
	}
	
	@Override
	public DocPermissions[] getDocUsers(int docId) throws RemoteException {
		PermissionsDAOSQL perDAO = new PermissionsDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","user");
		return perDAO.getDocCollaborators(docId);
		
	}
	
	@Override
	public void logout(UserInfo user) throws RemoteException {
		
		LoginDAOSQL logindao = new LoginDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","userprofile");
		logindao.removeIpPort(user.getUserid());
		onlineUsers.remove(user.getUserid());
		System.out.println ("user offline request");
		
		Iterator<Integer> r_main = onlineUsers.keySet().iterator();
		
		while(r_main.hasNext()) {
			int id = r_main.next();
			try {
				onlineUsers.get(id).userOffline(id);
			}
			catch (Exception e) {
				System.out.println ("user may be offline");
			}
		}
		
	}
	@Override
	public void syncClients(Map<Integer, Client> onlineUsers) throws RemoteException{
		
		Iterator<Integer> r_main = onlineUsers.keySet().iterator();
		
		while(r_main.hasNext()) {
			int id = r_main.next();
			if (this.onlineUsers.get(id) == null) {
				this.onlineUsers.put(id, onlineUsers.get(id));
			}
		}

	}

	public int createDoc ( int userid, String docname, String desc ) throws RemoteException{
		DocListDAOSQL docDAO = new DocListDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","document");
		Calendar calendar = Calendar.getInstance();
		SimpleDateFormat s1 = new SimpleDateFormat("MM/dd/yy"); // For current date
		String loc = "C:\\abhi\\"+docname+".txt";
		int newdocid = docDAO.insertDoc( docname, desc, s1.format(calendar.getTime()), userid, loc);
		return newdocid;
	}
	
	
	public void saveDoc(int userid, int docid, String contents) throws RemoteException{
		DocReadDAOSQL docread = new DocReadDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","document");
		//Check if the user is allowed to edit it or not
		PermissionsDAOSQL permdao = new PermissionsDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","permissions");
		String perm = permdao.getPerm(userid, docid);
		if(perm==null)
			return;
		if(perm.equalsIgnoreCase("readonly")){
			System.out.println("Not Enough Privilieges");
			return;
		}
		if(perm.equalsIgnoreCase("owner")||perm.equalsIgnoreCase("write")||perm.equalsIgnoreCase("edit")){
			docread.setDocContents(docid,contents);
			System.out.println("Successfully saved");
		}
	}
	public String editdoc(int docid) throws RemoteException{
		DocReadDAOSQL docread = new DocReadDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","document");
		String str = docread.getDocContents(docid);
		return str;
	}
	public DocPermissions[] shareDoc(int userid, int docid) throws RemoteException{
		PermissionsDAOSQL permissions = new PermissionsDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","permissions");
		DocPermissions[] docperm = permissions.getDocCollaborators(docid);
		return docperm;
	}
	public void insertPermission(int docid, int userid, String accesstype, int senderId) throws RemoteException{
		PermissionsDAOSQL permissions = new PermissionsDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","permissions");
		permissions.insertPerm(docid,userid,accesstype);
		//Here we can call permissions.getDocCollaborators(docid) to get all the users associated with the doc
		//The notify each of the user of the change in permissions
		DocPermissions[] docperm = permissions.getDocCollaborators(docid);
		Client s = null;
		/*Iterator it = onlineUsers.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry pairs = (Map.Entry)it.next();
			System.out.println("rrrrrrr"+pairs.getKey() + " = " + pairs.getValue());
		}
		 */

		for(int i=0;i<docperm.length;i++){
			
			if(senderId!= docperm[i].getUserid()){
				System.out.println("User Id for insertperm call = "+docperm[i].getUserid());
				s = onlineUsers.get(docperm[i].getUserid());
				s.newDocument(docid);
			}
		}


	}
	public void removePermission(int docid, int userid) throws RemoteException{
		PermissionsDAOSQL permissions = new PermissionsDAOSQL("com.mysql.jdbc.Driver","jdbc:mysql:///tecbox","permissions");
		permissions.removePerm(docid,userid);
	}


}	

